﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Roslyn.Compilers.CSharp;

namespace RoslynHelper
{
    public static class ClassDeclaration
    {
        public static ClassDeclarationSyntax SetGenericConstraintClauses(this ClassDeclarationSyntax node, IEnumerable<TypeParameterConstraintClauseSyntax> constraints)
        {
            return Syntax.ClassDeclaration(
                attributes: node.Attributes,
                modifiers: node.Modifiers,
                keyword: node.Keyword,
                identifier: node.Identifier,
                typeParameterListOpt: node.TypeParameterListOpt,
                baseListOpt: node.BaseListOpt,
                constraintClauses: Syntax.List<TypeParameterConstraintClauseSyntax>(constraints.Where(cc => cc != null)),
                openBraceToken: node.OpenBraceToken,
                members: node.Members,
                closeBraceToken: node.CloseBraceToken,
                semicolonTokenOpt: node.SemicolonTokenOpt);
        }

        public static ClassDeclarationSyntax AddMember(this ClassDeclarationSyntax node, MemberDeclarationSyntax member)
        {
            return AddMembers(node, new[] { member });
        }

        public static ClassDeclarationSyntax AddMembers(this ClassDeclarationSyntax node, IEnumerable<MemberDeclarationSyntax> members)
        {
            return DefineMembers(node, node.Members.Union(members));
        }

        public static ClassDeclarationSyntax DefineMembers(this ClassDeclarationSyntax node, IEnumerable<MemberDeclarationSyntax> members)
        {
            return Syntax.ClassDeclaration(
                attributes: node.Attributes,
                modifiers: node.Modifiers,
                keyword: node.Keyword,
                identifier: node.Identifier,
                typeParameterListOpt: node.TypeParameterListOpt,
                baseListOpt: node.BaseListOpt,
                constraintClauses: node.ConstraintClauses,
                openBraceToken: node.OpenBraceToken,
                members: Syntax.List<MemberDeclarationSyntax>(members),
                closeBraceToken: node.CloseBraceToken,
                semicolonTokenOpt: node.SemicolonTokenOpt);
        }

        public static ClassDeclarationSyntax AddInterface(this ClassDeclarationSyntax node, string typeName)
        {
            return Syntax.ClassDeclaration(
                attributes: node.Attributes,
                modifiers: node.Modifiers,
                keyword: node.Keyword,
                identifier: node.Identifier,
                typeParameterListOpt: node.TypeParameterListOpt,
                baseListOpt: Syntax.BaseList(
                types: SeparatedList.Create((node.BaseListOpt == null ? Enumerable.Empty<TypeSyntax>() : node.BaseListOpt.Types).Union(new[] { Syntax.ParseTypeName(typeName) }))),
                constraintClauses: node.ConstraintClauses,
                openBraceToken: node.OpenBraceToken,
                members: node.Members,
                closeBraceToken: node.CloseBraceToken,
                semicolonTokenOpt: node.SemicolonTokenOpt);
        }

        public static ClassDeclarationSyntax DefineAttributes(this ClassDeclarationSyntax node, IEnumerable<AttributeDeclarationSyntax> attributes)
        {
            return Syntax.ClassDeclaration(
                attributes: Syntax.List<AttributeDeclarationSyntax>(attributes.Where(a => a != null)),
                modifiers: node.Modifiers,
                keyword: node.Keyword,
                identifier: node.Identifier,
                typeParameterListOpt: node.TypeParameterListOpt,
                baseListOpt: node.BaseListOpt,
                constraintClauses: node.ConstraintClauses,
                openBraceToken: node.OpenBraceToken,
                members: node.Members,
                closeBraceToken: node.CloseBraceToken,
                semicolonTokenOpt: node.SemicolonTokenOpt);
        }
    }
}
